package com.ai.enviro.config;



import com.ai.enviro.common.BaseResponse;
import com.ai.enviro.common.CodeEnum;
import com.ai.enviro.exception.ServiceException;
import com.ai.enviro.exception.ValidateException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * 全局异常处理器，将 Exception 翻译成 CommonResult + 对应的异常编号
 *
 */
@RestControllerAdvice
@AllArgsConstructor
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 校验异常
     * @param req
     * @param ex
     * @return
     */
    @ExceptionHandler(value = {ValidateException.class,MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.OK)
    public BaseResponse<?> validateExceptionHandler(HttpServletRequest req, Throwable ex) {
        return allExceptionHandler(req,ex);
    }

    @ExceptionHandler(value = ServiceException.class)
    @ResponseStatus(HttpStatus.OK)
    public BaseResponse<?> serviceExceptionHandler(HttpServletRequest req, Throwable ex) {
        log.error("[serviceExceptionHandler]", ex);
        return allExceptionHandler(req,ex);
    }
    /**
     * 处理系统异常，兜底处理所有的一切
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public BaseResponse<?> defaultExceptionHandler(HttpServletRequest req, Throwable ex) {
        log.error("[defaultExceptionHandler]", ex);
        // 插入异常日志
        this.createExceptionLog(req, ex);
        // 返回通用异常
        return allExceptionHandler(req,ex);
    }

    /**
     * 创建异常日志
     * @param req HttpServletRequest对象
     * @param ex Throwable对象
     */
    private void createExceptionLog(HttpServletRequest req, Throwable ex) {
        // TODO: 在这里实现创建异常日志的逻辑
    }

    /**
     * 处理所有异常，主要是提供给 Filter 使用
     * 因为 Filter 不走 SpringMVC 的流程，但是我们又需要兜底处理异常，所以这里提供一个全量的异常处理过程，保持逻辑统一。
     *
     * @param request 请求
     * @param ex 异常
     * @return 通用返回
     */
    public BaseResponse<?> allExceptionHandler(HttpServletRequest request, Throwable ex) {
        if (ex instanceof ValidateException) {
            ValidateException validateException = (ValidateException) ex;
            return new BaseResponse<>(validateException.getCode(),validateException.getMessage());
        }
        if (ex instanceof ServiceException) {
            ServiceException serviceException = (ServiceException) ex;
            return new BaseResponse<>(serviceException.getCode(),serviceException.getMessage());
        }
        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) ex;
            String errMsg = methodArgumentNotValidException.getBindingResult().getAllErrors()
                    .stream().map(error -> error.getDefaultMessage()).findFirst().orElse(CodeEnum.PARAM_ERROR.getMsg());
            return new BaseResponse<>(CodeEnum.PARAM_ERROR.getCode(),errMsg);
        } else if (ex instanceof BindException) {
            BindException bindException = (BindException) ex;
            String errMsg = bindException.getAllErrors()
                    .stream().map(error -> error.getDefaultMessage()).findFirst().orElse(CodeEnum.PARAM_ERROR.getMsg());
            return new BaseResponse<>(CodeEnum.PARAM_ERROR.getCode(),errMsg);
        }
        return new BaseResponse<>(CodeEnum.SYSTEM_ERROR.getCode(), CodeEnum.SYSTEM_ERROR.getMsg());
    }


}
